package com.tan.core.utils;


import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author Tan
 * @description
 * @date 2025/1/27
 */
@Component
public class ThreadPoolTool {

    @Value("${thread.pool.core-pool-size:32}")
    private Integer corePoolSize;

    @Value("${thread.pool.max-pool-size:128}")
    private Integer maxPoolSize;

    @Value("${thread.pool.queue-capacity:200}")
    private Integer queueCapacity;

    @Value("${thread.pool.keep-alive-time:60}")
    private Integer keepAliveTime;

    @Value("${thread.pool.name-prefix}")
    private String namePrefix;

    @Value("${websocket-main.port}")
    private Integer port;

    @Resource
    private ThreadPoolTaskExecutor taskExecutor;
    private final AtomicInteger taskCount = new AtomicInteger(0);


    @PostConstruct
    public void init() {
        // 设置核心线程数
        taskExecutor.setCorePoolSize(corePoolSize);
        // 设置最大线程数
        taskExecutor.setMaxPoolSize(maxPoolSize);
        // 设置线程池队列大小
        taskExecutor.setQueueCapacity(queueCapacity);
        // 设置线程名称前缀，方便在日志或调试中识别
        taskExecutor.setThreadNamePrefix(namePrefix);
        // 设置线程存活时间（单位：秒）当线程池中的线程数量超过核心线程数，且空闲时间超过 60 秒时，这些多余的线程将会被终止。
        taskExecutor.setKeepAliveSeconds(keepAliveTime);
        // 初始化线程池
        taskExecutor.initialize();
    }

    /**
     * 执行一个 Runnable 任务
     *
     * @param task 要执行的任务
     */
    public void execute(Runnable task) {
        // 增加任务计数
        taskCount.incrementAndGet();
        taskExecutor.execute(task);
    }


    /**
     * 提交一个 Callable 任务，并返回 Future 用于获取结果
     * Callable<String> task = () -> {
     * return "Task completed successfully!";
     * };
     * Future<String> future = threadPool.submit(task);
     * future.get()
     *
     * @param task 要提交的任务
     * @param <T>  任务返回值类型
     * @return Future 对象
     */
    public <T> Future<T> submit(Callable<T> task) {
        // 增加任务计数
        taskCount.incrementAndGet();
        return taskExecutor.submit(task);
    }

    /**
     * 等待所有任务完成
     *
     * @throws InterruptedException 如果等待被中断
     */
    public void awaitTermination() throws InterruptedException {
        // 当还有未完成的任务时，每隔 1 秒检查一次
        while (taskCount.get() > 0) {
            Thread.sleep(1000);
        }
        // 等待线程池终止，最长等待 10 秒
        taskExecutor.setAwaitTerminationSeconds(10);
    }

    /**
     * 关闭线程池
     */
    public void shutdown() {
        taskExecutor.shutdown();
    }

    /**
     * 获取当前正在执行的任务数量
     *
     * @return 正在执行的任务数量
     */
    public int getActiveCount() {
        return taskExecutor.getActiveCount();
    }

    /**
     * 获取排队中未执行的任务数量
     *
     * @return 排队中未执行的任务数量
     */
    public int getQueueSize() {
        return taskExecutor.getThreadPoolExecutor().getQueue().size();
    }
}